using System;
using System.Collections.Generic;
using System.Text;
using WMEncoderLib;
using Xivo.Shared;

namespace WMRecorder
{
  /// <summary>
  /// Provides the interface and some support routines for recording audio files to disk.
  /// You should override the RecordFile and StopRecording functions to actually perform
  /// and end recording.
  /// </summary>
  public class RecordModule : IXivoRecorder
  {
    bool SplitRecordings = true;
    event Delegates.StringEvent _onFilenameChange;
    public string _RecordPath;
    bool recording = false;
    int EncoderIndex = 0;
    WMEncoder[] Encoders = new WMEncoder[2];
    DateTime StartTime;
    string _RecordSource = "Default_Audio_Device";


    string oldArtist = "";
    ChannelInfo info;
    public ChannelInfo Info
    {
      get
      {
        return info;
      }
      set
      {
        info = value;

        //System.Diagnostics.Debug.WriteLine("old ShortArtist: " + oldArtist);
        //System.Diagnostics.Debug.WriteLine("new ShortArtist: " + info.shortArtist);

        string filename;
        if (recording)
        {
          if (SplitRecordings && oldArtist != info.shortArtist)
            RestartRecording_new();
          filename = Encoders[EncoderIndex].File.LocalFileName;
        }
        else
          filename = info.getFileName();
        if (_onFilenameChange != null)
          _onFilenameChange(filename);
        oldArtist = info.shortArtist;
      }
    }

    /// <summary>
    /// not implemented. need to fix later, if we keep using this module.
    /// </summary>
    public string FileName {
      get { return ""; }
      set { }
    }

    private void RestartRecording_old()
    {
      Encoders[EncoderIndex].Stop();
      StartRecording();
    }

    private void RestartRecording_new()
    {
      int oldIndex = EncoderIndex;
      EncoderIndex = (EncoderIndex + 1) % Encoders.Length;
      StartRecording();
      System.Threading.Thread.Sleep(5000);
      Encoders[oldIndex].Stop();
    }

    public RecordModule()
    {
      if (Xivo.Shared.Common.Radio != null) {
        Xivo.Shared.Common.Radio.onChannelInfoChange += new Delegates.InfoEvent(Radio_onChannelInfoChange);
        for (int i = 0; i < Encoders.Length; ++i)
          Encoders[i] = new WMEncoder();
      }
    }

    void Radio_onChannelInfoChange(ChannelInfo info) {
      this.Info = info;
    }

    public void StartRecording()
    {
      StartRecording(null,true);
    }

    /// <summary>
    /// Start recording. The current track information will be used.
    /// </summary>
    /// 
    /// <param name="fileName">File name. Leave blank to split recoridngs based on channel info</param>
    public void StartRecording(ChannelInfo info, bool SplitRecordings)
    {
      if (info == null)
        info = this.info;
      else
        this.info = info;
      this.SplitRecordings = SplitRecordings;

      WMEncoder currEncoder = Encoders[EncoderIndex];
      if (recording)
        currEncoder.Stop();

      // Specify the source for the input stream.
      IWMEncSourceGroupCollection SrcGrpColl = currEncoder.SourceGroupCollection;
      IWMEncSourceGroup SrcGrp = SrcGrpColl.Add("SG_1");
      IWMEncSource SrcAud = SrcGrp.AddSource(WMENC_SOURCE_TYPE.WMENC_AUDIO);
      SrcAud.SetInput(RecordSource, "Device", "");

      // Specify a profile.
      IWMEncProfile Pro;
      IWMEncProfileCollection ProColl = currEncoder.ProfileCollection;

      for (int i = 0; i < ProColl.Count; i++)
      {
        Pro = ProColl.Item(i);
        //System.Diagnostics.Debug.WriteLine(Pro.Name);
        if (Pro.Name == "Windows Media Audio 8 for Dial-up Modem (CD quality, 64 Kbps)")
        {
          SrcGrp.set_Profile(Pro);
          break;
        }
      }

      string Filename = System.IO.Path.Combine(_RecordPath, info.getFileName());
      if (Filename.ToLower().EndsWith(".wma") == false)
        Filename = Filename + ".wma";
      currEncoder.File.LocalFileName = Filename;

      // set the tag properties
      IWMEncDisplayInfo desc;
      desc = currEncoder.DisplayInfo;
      desc.Title = info.longTitle;
      desc.Author = info.longArtist;
      desc.Description = info.station + " " + info.channelStr + " " +
        DateTime.Now.ToLongDateString() +
        " " + DateTime.Now.ToLongTimeString();

      // Start the encoding process.
      recording = true;
      currEncoder.PrepareToEncode(true);
      currEncoder.Start();
      StartTime = DateTime.Now;
    }

    /// <summary>
    /// Stop recording the file. 
    /// </summary>
    public void StopRecording()
    {
      Encoders[EncoderIndex].Stop();
      recording = false;
    }

    virtual public bool Recording
    {
      set { recording = value; }
      get { return recording; }
    }

    public string State
    {
      get
      {
        WMEncoder currEncoder = Encoders[EncoderIndex];
        if (currEncoder != null)
        {
          string State;
          switch (currEncoder.RunState)
          {
            case WMENC_ENCODER_STATE.WMENC_ENCODER_END_PREPROCESS:
              State = "End_Preprocess";
              break;
            case WMENC_ENCODER_STATE.WMENC_ENCODER_PAUSED:
              State = "Paused";
              break;
            case WMENC_ENCODER_STATE.WMENC_ENCODER_PAUSING:
              State = "Pausing";
              break;
            case WMENC_ENCODER_STATE.WMENC_ENCODER_RUNNING:
              State = "Running";
              break;
            case WMENC_ENCODER_STATE.WMENC_ENCODER_STARTING:
              State = "Starting";
              break;
            case WMENC_ENCODER_STATE.WMENC_ENCODER_STOPPED:
              State = "Stopped";
              break;
            case WMENC_ENCODER_STATE.WMENC_ENCODER_STOPPING:
              State = "Stopping";
              break;
            default:
              State = "Unknown";
              break;
          }
          return State;
        }
        else
        {
          return "Not loaded";
        }
      }
    }

    void recordException(Exception ex)
    {
      System.IO.StreamWriter outf = new System.IO.StreamWriter("errors.txt", true);
      outf.WriteLine("Exception on " + DateTime.Now.ToString());
      outf.WriteLine(ex.Message);
      outf.WriteLine(ex.Source);
      outf.WriteLine(ex.StackTrace);
      outf.WriteLine();
      outf.Close();
    }

    #region IXivoRecorder Members

    public event Delegates.StringEvent onFilenameChange {
      add { this._onFilenameChange += value; }
      remove { this._onFilenameChange -= value; }
    }

    public string RecordPath {
      get {
        return this._RecordPath;
      }
      set {
        this._RecordPath = value;
      }
    }

    public string RecordSource {
      get {
        return this._RecordSource;
      }
      set {
        this._RecordSource = value;
      }
    }

    public TimeSpan RecordTime {
      get {
      return System.DateTime.Now - StartTime;
      }
    }

    public string RecordTimeStr {
      get {
        TimeSpan ts = RecordTime;
        return ts.Hours.ToString("00") + ":" +
          ts.Minutes.ToString("00") + ":" +
          ts.Seconds.ToString("00");
      }
    }

    public System.Windows.Forms.Control getOptionPanel() {
      return new OptionsPanel();
    }

    #endregion
  }
}
